/*
 Функциональное описание:

*/
`timescale 1ns / 10ps
//    ********************** НАЧАЛО МОДУЛЯ *********************************************************
module mod_sync_gen
    (   input  logic            reset_n,
        input  logic            clk,
        input  logic            start,
        
        output logic            vldata_o,
        output logic            vrdata_o,
        output logic            vhdata_o,
        output logic            vlsync_o,
        output logic            vrsync_o,
        output logic            vhsync_o,
        output logic            vsample_o,
        output logic            vclamp_o,
        
        input  logic [31:0]    data_param,
        output logic [31:0]    addr_param,
        
        input logic [15:0]     adc_data,
        
        output logic [15:0]    image_data,
        output logic           image_data_wre,
        output logic [31:0]    image_data_addr,
        
        output logic            sof,
        output logic            eof,
        
        output logic            cdsclk1,
        output logic            cdsclk2,
        output logic            adcclk
    );
    
// ********************** МАКРОСЫ ******************************************************************
    // Описывает процесс модуля выделения фронтов сигнала. 
    // Так же описывает создание новых сигналов с именем <имя сигнала> + <_rise> (<_fall>, <_edge>)
    `define front(clk, name)                    \
    logic name``_0;                             \
    logic name``_1;                             \
    logic name``_rise;                          \
    logic name``_fall;                          \
    logic name``_edge;                          \
    always_ff @(posedge clk)                    \
    begin                                       \
        name``_0 <= name;                       \
        name``_1 <= name``_0;                   \
        name``_rise <= name``_0 & (~name``_1);  \
        name``_fall <= name``_1 & (~name``_0);  \
        name``_edge <= name``_0 ^ name``_1;     \
    end
//    ********************* КОНСТАНТЫ **************************************************************
    localparam ch_num_lp    = 13;
    localparam wl_p         = $clog2(ch_num_lp);
    
//    ********************* СОЗДАНИЕ И ОПИСАНИЕ ПЕРЕМЕННЫХ *****************************************
    logic [31:0]                sync_imp;
    
    logic [ch_num_lp-1:0]       imp;
    logic [ch_num_lp-1:0]       wre;
    
    // logic                       sof;    
    logic                       adc_stb;
    
    
//  ********************* БЛОК НЕПРЕРЫВНЫХ НАЗНАЧЕНИЙ ASSIGN ***************************************
    assign 
    {    
        adcclk,
        cdsclk2,
        cdsclk1,
        sof,
        adc_stb,
        vclamp_o, 
        vsample_o, 
        vhsync_o,
        vhdata_o, 
        vlsync_o, 
        vldata_o,
        vrsync_o, 
        vrdata_o
    }   = imp;
    
    assign sync_imp     = {18'd0, imp, start};

  
//  ********************* ОПИСАНИЕ ПРОЦЕССОВ *******************************************************
    `front (clk, vhsync_o)    
    `front (clk, vlsync_o)    
    `front (clk, adc_stb)        
    `front (clk, sof)       
    
    always_comb
    begin
        wre                         = {ch_num_lp{1'b0}};
        wre[addr_param[wl_p+3:4]]   = 1'b1;
    end
    
    always_ff @(posedge clk)
    begin
        addr_param  <= addr_param + 32'd1;
        
        // sof         <= vrdata_o;
        if ((image_data_addr >= 32'd76799) && image_data_wre) 
            eof <= 1'b1;
        else    
            eof <= 1'b0;
    end

    always_ff @(posedge clk)
    begin
        if (sof_rise)
            image_data_addr <= 10'd0;
        else if (adc_stb_fall)
            image_data_addr <= image_data_addr + 10'd1;
        else;

        image_data_wre  <= adc_stb;
        if (adc_stb) begin
            image_data  <= adc_data;
        end
        else;
    end
    
//  ********************* ПОДКЛЮЧЕНИЕ МОДУЛЕЙ ******************************************************
    
    genvar ch;
    generate
        for (ch = 0; ch < ch_num_lp; ch++) begin  : gen_mod_impulse_gen
            mod_impulse_gen_group
            mod_impulse_gen_group_inst
                (   .clk        (clk),
                    .reset_n    (reset_n), 
                    .sync_imp   (sync_imp),
                    .addr       (addr_param[3:0]),
                    .data       (data_param),
                    .wre        (wre[ch]),

                    .imp        (imp[ch])
                );
        end
    endgenerate
    
endmodule